#include "stdafx.h"

#ifndef WIN32

#include <stdio.h>
#include <time.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <assert.h>
#include <signal.h>

#include <pthread.h>

#include<sys/types.h>
#include<sys/stat.h> 
#else



#endif

 #include "math.h"


 
#include "../../../include/common/base.h" 
#include "../../../include/rtdbms/rtdb_sys.h"

#include "../../../include/common/share_memory_api.h"

struUsrPointer  LibDetails[MaxLibNo + 1];
struShareMen*  SysPtr=0;
HANDLE          SysHandle;

 
bool LoadRtdbVersion();  

bool OpenDbms()
{
	char HostName[100];
	strcpy(HostName,"");
	// map view of file for the current process
	int 	BlockSize;
	char    MapName[MAX_NAME_LEN + 12];
	struLibrary* pLib;
	int    first_flag;

#ifndef WIN32
	SysPtr = (struShareMen*)CreateShmMap("LN_DBMS_SYSMEM", sizeof(struShareMen), &first_flag,  "/rtdbms/" );
#else
	SysPtr = (struShareMen*)CreateShmMapWin("LN_DBMS_SYSMEM", sizeof(struShareMen), &first_flag, SysHandle, RTDB_PAHT );
#endif
 	
    //printf("OpenDbms \n");

    if ( SysPtr == 0)
    { 
		printf("OpenDbms error \n");
    		return false;
    }

    if( first_flag == shm_open_create )
	{
		memset(SysPtr, 0, sizeof(struShareMen));
		printf("OpenDbms shm_open_create \n");
	} 

	LoadRtdbVersion();
	
	//printf("openDbms : rtdb version = %d(%s) \n", SysPtr->curRtdbVersion, RTDB_VERSION_NAME(SysPtr->curRtdbVersion) );

	for( int i=0; i<MaxLibNo; i++ )
	{
		if(SysPtr->TheLibMsgArray[i].IsUsed == ISUSED)
		{
			pLib = &(SysPtr->TheLibMsgArray[i]);  

			strcpy(MapName, pLib->libInfo.NAME); 
			strcat(MapName, "-");
			strcat(MapName, "BlockMap");
			
			//printf("OpenDbms: %s \n", MapName);

			BlockSize =  pLib->libInfo.retc_width * pLib->libInfo.LibSize;

			int open_flag; 
#ifndef WIN32
			LibDetails[i].m_pRecords =  CreateShmMap(MapName, BlockSize, &open_flag,  "/rtdbms/");
#else
			LibDetails[i].m_pRecords =  CreateShmMapWin(MapName, BlockSize, &open_flag, pLib->BlockHandle, RTDB_PAHT);
#endif

			if( LibDetails[i].m_pRecords == NULL ) continue; 

			if( open_flag == shm_open_create )
			{
				memset( LibDetails[i].m_pRecords, 0, BlockSize );
			}
		}


	}
	 
	return true;
}

  

bool IsLoadDbms()
{
	char HostName[100];
	strcpy(HostName,"");
	// map view of file for the current process
	int 	BlockSize;
	char    MapName[MAX_NAME_LEN + 12];
	struLibrary* pLib;
	int    first_flag;

#ifndef WIN32
	SysPtr = (struShareMen*)CreateShmMap("LN_DBMS_SYSMEM", sizeof(struShareMen), &first_flag,  "/rtdbms/" );
#else
	SysPtr = (struShareMen*)CreateShmMapWin("LN_DBMS_SYSMEM", sizeof(struShareMen), &first_flag, SysHandle, RTDB_PAHT);
#endif
 	
    //printf("OpenDbms \n");

    if ( SysPtr == 0)
    { 
		printf("OpenDbms error \n");
    		return false;
    }

    	if( first_flag == shm_open_create )
	{
		memset(SysPtr, 0, sizeof(struShareMen));
		printf("OpenDbms shm_open_create \n"); 
		return false;
	} 

	 
	for( int i=0; i<MaxLibNo; i++ )
	{
		if(SysPtr->TheLibMsgArray[i].IsUsed == ISUSED)
		{
			 return true;			 
		} 
	}
	 
	return false;
}



bool IsLibNoValid(short TheLibNo)
{
    // invalid : return 0;    valid : return 1
	if( SysPtr == NULL ) return false;

    if(((unsigned short)TheLibNo > MaxLibNo) || (SysPtr->TheLibMsgArray[TheLibNo].IsUsed != ISUSED))  return false ;
    
    return true;
}                                                                       


void DestroyLib(short TheLibNo)              
{
	    if( !IsLibNoValid(TheLibNo) )    return ;
    
        struLibrary* pTempLib;
        pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
		 
        // set IFUSED = NOTUSED        loaded lib count --
		SysPtr->TheLibMsgArray[TheLibNo].IsUsed = NOTUSED;
        SysPtr->TheLibCount --;
}



int ReadEx(int fd, char * buf,  int size_count )
{
    int  size = size_count;
    int total_read_bytes = 0;
    while( total_read_bytes < size_count )
    {
        int read_bytes  = read( fd, &buf[total_read_bytes], size );
        if( read_bytes <= 0 ) break;

        total_read_bytes+=read_bytes;
        size = size_count - total_read_bytes;
    }

    return total_read_bytes;
}


bool ReadAll_Memory(short TheLibNo, int & fd, int RecCount, int BlockSize) 
{
	if( fd <= 0 ) return false;

    struLibrary* pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
  
    int read_size = 0;
	read_size = ReadEx( fd, (char*)LibDetails[TheLibNo].m_pRecords, BlockSize);
	 
	pTempLib->libInfo.RecCount = RecCount ;
  
	return true ;
}

 
int findPrime(int first, int end)
{
	int n , i, j;
	i = j = 0;

	int max_n =0;

	for( i=first; i<=end; i++ )
	{
		n = (int)sqrt((double)i);
		for( j=2; j<=n; j++ )
		{
			if( i % j == 0 ) 
				break; 
		}
		if( j > n )
		{
			/*char buf[10];
			memset(buf, 0, 10);
			sprintf(buf, "%d", i); 
			printf( buf );*/
			max_n = i;
		}
		 

	}
	return max_n;
}
 

bool InitLib(short TheLibNo,struLibInfo & TheLibInfo)
{
    // check LibNo valid , notused
    if((unsigned short)TheLibNo > MaxLibNo) 
    { 
    	return false;
	}

	if ( SysPtr == 0)
	{
 		return false;
	} 
	 
	if(SysPtr->TheLibMsgArray[TheLibNo].IsUsed != NOTUSED)   
    { 
    	return false;        
	} 
    
    // get the point of the tablet
    struLibrary* pLib;
    pLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
    
	memcpy(&pLib->libInfo, &TheLibInfo, sizeof(struLibInfo));
     

	
	 // reset them				 
	pLib->libInfo.RecCount = 0; 

	int max_f = findPrime( pLib->libInfo.LibSize/2, pLib->libInfo.LibSize );
	/*if( max_f > 0 )
		pLib->BaseCount = max_f;
	else*/
		pLib->BaseCount = (pLib->libInfo.LibSize - pLib->libInfo.LibSize  / 10) /2 * 2 - 1 ;
	 
	if( pLib->BlockHandle > 0 ) return true;
  
	char    MapName[MAX_NAME_LEN + 12];
	strcpy(MapName, pLib->libInfo.NAME);
	strcat(MapName, "-");
	strcat(MapName, "BlockMap");

 
	int BlockSize  = pLib->libInfo.LibSize *  pLib->libInfo.retc_width ;

	int first_flag = -1;

#ifndef WIN32
	LibDetails[pLib->libInfo.LibNo].m_pRecords = CreateShmMap(MapName, BlockSize, &first_flag,  "/rtdbms/"); 
#else
	LibDetails[pLib->libInfo.LibNo].m_pRecords = CreateShmMapWin(MapName, BlockSize, &first_flag, pLib->BlockHandle, RTDB_PAHT); 
#endif

	SysPtr->TheLibMsgArray[TheLibNo].IsUsed = ISUSED;
    SysPtr->TheLibCount ++;

	memset(LibDetails[pLib->libInfo.LibNo].m_pRecords, 0, BlockSize);

	return true;
}



bool LoadLibFile(char  * TheFileName, short TheLibNo)
{
	// check the lib No. is valid
    if((TheLibNo > MaxLibNo) || ((TheLibNo < 0) && (TheLibNo != -1)))  return false ; 
    
    // check the lib No. is not used
    if(SysPtr->TheLibMsgArray[TheLibNo].IsUsed == ISUSED)  return false ;

	int fd  = 0;
#ifdef WIN32    
    fd = open(TheFileName, O_RDONLY  | O_BINARY );
#else 
	fd = open(TheFileName, O_RDONLY );
#endif

    if(fd < 0 )  return false;
	 
   
	short VersionID; 
 
    lseek(fd, 0, SEEK_SET); 
    int r2 = ReadEx( fd, (char*)&VersionID, sizeof(short));
  
  
    struLibInfo * pLibInfo = new struLibInfo;
    if(pLibInfo == 0)
    {
        close( fd );
        return false;
    }
        
    short TempLibNo ;
 
	read( fd, &TempLibNo, sizeof(short));
	read( fd, pLibInfo, sizeof(struLibInfo));
                               
    
    // if TempLibNo == -1, use the lib no in the file   else use TempLibNo
    if(TempLibNo != TheLibNo) 
	{
		delete pLibInfo;
		close( fd );
		return false;
	}   
     
    // restore the rec count
    int RecCount = pLibInfo->RecCount ;
        
    bool OutMsg;
 
	if((OutMsg = InitLib(TempLibNo, *pLibInfo)) != true)
    { 
        delete pLibInfo;
 		close(fd);
        return  false;    
    }
         
    delete pLibInfo;	 
 
    struLibrary*  pTempLib = &(SysPtr->TheLibMsgArray[TempLibNo]);
         
    if(RecCount == 0) 
    {
 		close( fd );
        return false;
    }            

	int BlockSize  = pTempLib->libInfo.LibSize *  pTempLib->libInfo.retc_width ;
	 
 
    OutMsg = ReadAll_Memory(TempLibNo, fd, RecCount, BlockSize) ;  
        
    close( fd );    

    return OutMsg; 
}


bool WriteAll_Memory(short TheLibNo, int & fd) 
{
    struLibrary* pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
	 
	int num = write( fd, LibDetails[TheLibNo].m_pRecords, pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width ) ;

	return true; 
}
bool SaveLibFile(char  * TheFileName, short TheLibNo)
{
    if( !IsLibNoValid(TheLibNo) )   return false; 

    struLibrary* pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
     
	int fd = -1;
  
#ifdef WIN32    
    fd = open(TheFileName, O_CREAT  | O_BINARY | O_RDWR, S_IWRITE );
#else
	fd = open(TheFileName, O_CREAT | O_RDWR ,   S_IWRITE );
#endif 
        
	if( fd < 0 ) return false;
	 
    
	short VersionID = 100; 
 	 
	write( fd, &VersionID, sizeof(short));  // VersionID  
	write( fd, &TheLibNo, sizeof(short)); // lib no
	write( fd, pTempLib, sizeof(struLibInfo));   // lib inforamtion
	 
		
	if(pTempLib->libInfo.RecCount == 0) 
    {
        close( fd );
        return false;
    }            
         
		 
     bool OutMsg = WriteAll_Memory(TheLibNo, fd) ; 
	
	close( fd );
                           
    return OutMsg; 
}



bool CheckCanBeUsedByLibNo( int lib_no )
{
	if( lib_no <= 0 || lib_no > MaxLibNo ) {
		printf("CheckCanBeUsedByLibNo false: lib_no=%d \n", lib_no);
		return false;
	}
	
	if( SysPtr ) {
		if( SysPtr->TheLibMsgArray[lib_no].IsUsed == ISUSED )  {
			//printf("CheckCanBeUsedByLibNo false: lib_no=%d is used \n", lib_no);
			return false ;  //已经被是使用
		}
	}
	
	return true;
}

 

void CloseDbms()
{
	// unmap view of file for the current process
 
	if(SysPtr)
	{
		for(int i = 0; i <= MaxLibNo; i ++)
		{
			struLibrary * pTempLib = &(SysPtr->TheLibMsgArray[i]);
			if(pTempLib->IsUsed == ISUSED)
			{
				int BlockSize =  pTempLib->libInfo.retc_width * pTempLib->libInfo.LibSize;
				
				DestoryShmMap(LibDetails[pTempLib->libInfo.LibNo].m_pRecords, BlockSize);
				
				char    MapName[MAX_NAME_LEN + 12];
				strcpy(MapName, pTempLib->libInfo.NAME);
				strcat(MapName, "-");
				strcat(MapName, "BlockMap");
				Shamunlink(MapName);
			}
		}
		
		DestoryShmMap(SysPtr, sizeof(struShareMen));
	} 

    Shamunlink("LN_DBMS_SYSMEM");

 
}

 /*
bool set_rtdb_version( unsigned int ver )
{
	if( SysPtr == NULL ) return 0;

	//SysPtr->curRtdbVersion = ver;

	//printf("set rtdb version = %d(%s) \n", SysPtr->curRtdbVersion, RTDB_VERSION_NAME(SysPtr->curRtdbVersion) );
	return false;
}

int  get_rtdb_Version()
{
	if( SysPtr == NULL ) return 0;
	
	//printf("get rtdb version = %d(%s) \n", SysPtr->curRtdbVersion, RTDB_VERSION_NAME(SysPtr->curRtdbVersion) );

	//return SysPtr->curRtdbVersion;
	return 0;
}*/

bool SaveRtdbVersion()
{
	/*if(SysPtr)
	{
		char chrPathDbName[128];
		memset(chrPathDbName, 0, 128);
		sprintf(chrPathDbName, "%s//ShareMenDB.ver", RTDB_PAHT);   

		int fd = -1;
		fd = open(chrPathDbName, O_CREAT | O_RDWR ,   S_IWRITE );
		if( fd < 0 ) return false;

		write( fd, &SysPtr->curRtdbVersion, sizeof(int));  // rtdb version

		close( fd );
		
		return 	true;
	}*/
	return false;
}
bool LoadRtdbVersion()
{
	/*if(SysPtr)
	{
		char chrPathDbName[128];
		memset(chrPathDbName, 0, 128);
		sprintf(chrPathDbName, "%s//ShareMenDB.ver", RTDB_PAHT);   

		int fd = -1;
		fd = fd = open(chrPathDbName, O_RDONLY );
		if(fd < 0 )  {
			return false;
		}

		lseek(fd, 0, SEEK_SET); 
    		int r2 = ReadEx( fd, (char*)&SysPtr->curRtdbVersion, sizeof(int));
 
		close( fd );

		return true;
	}*/

	return false;
}


bool SaveLibToMem(short TheLibNo, char  * pBuff, long BuffSize)
{
    if(!IsLibNoValid(TheLibNo))   return false;
    
    struLibrary* pTempLib;
    pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);

	long RealBuffSize;

	RealBuffSize = (sizeof(short)  + sizeof(short) + 
				sizeof(struLibInfo) +  pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width);
	
	if(BuffSize < RealBuffSize)
		return false;
 
	short VersionID = 100; 
	long FileIp = 0;

    memcpy(pBuff + FileIp, &VersionID, sizeof(short));  // file id
	FileIp += sizeof(short);
     
    memcpy(pBuff + FileIp, &TheLibNo, sizeof(short)); // lib no
	FileIp += sizeof(short);
    
    memcpy(pBuff + FileIp, pTempLib, sizeof(struLibInfo));   // lib inforamtion
	FileIp += sizeof(struLibInfo);
	 
	memcpy(pBuff + FileIp, LibDetails[TheLibNo].m_pRecords, pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width ) ;
	 
	return true;
}


bool  LoadLibFromMem(short TheLibNo, char* pBuff, long BuffSize)
{
    // check the lib No. is valid
    if((TheLibNo > MaxLibNo) || ((TheLibNo < 0) && (TheLibNo != -1)))  return false ; 
    
    // check the lib No. is not used
	struLibrary * pTempLib = &(SysPtr->TheLibMsgArray[TheLibNo]);
	if(pTempLib->IsUsed == ISUSED) return false;
	 
	long RealBuffSize;

	// check the buff size first
	RealBuffSize =  sizeof(short) + sizeof(short) + sizeof(struLibInfo);
	
	if(BuffSize < RealBuffSize)
		return false;

 
	short VersionID; 
	long FileIp = 0;
	 
    memcpy(&VersionID, pBuff + FileIp, sizeof(short));
	FileIp += sizeof(short);
	 
    struLibInfo* pLibInfo;
    pLibInfo = new struLibInfo;
    if(pLibInfo == NULL)
        return false;
        
    short TempLibNo;
    memcpy(&TempLibNo, pBuff + FileIp, sizeof(short)) ;
	FileIp += sizeof(short);

    memcpy(pLibInfo, pBuff + FileIp, sizeof(struLibInfo));
	FileIp += sizeof(struLibInfo);
                        
        
    // if TheLibNo == -1, use the lib no in the file   else use TheLibNo
    if(TheLibNo != -1)  TempLibNo = TheLibNo;

	// check the buff size second
	RealBuffSize = (sizeof(short)  + sizeof(short) + 
				sizeof(struLibInfo) +  pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width);
	
	if(BuffSize < RealBuffSize)
	{
		delete pLibInfo;
		return false;
	}
	  
    // restore the rec count
    long RecCount = pLibInfo->RecCount ;
        
    bool OutMsg;
    if((OutMsg = InitLib(TempLibNo, *pLibInfo)) != true)
    { 
        delete pLibInfo;
        return false;
    } 
    delete pLibInfo;
	  
    if(RecCount == 0) 
        return 0;
     

	memcpy(LibDetails[TheLibNo].m_pRecords,  pBuff + FileIp, pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width);
		
	FileIp += pTempLib->libInfo.LibSize * pTempLib->libInfo.retc_width;
            
	// need to set pTempLib->RecCount by yourself 
	pTempLib->libInfo.RecCount = RecCount ; 
	  
      

	return true;
}
